import tensorflow as tf
from tensorflow import keras
from sklearn.datasets import fetch_california_housing
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import numpy as np

dataset = fetch_california_housing()
train_x, test_x, train_y, test_y = train_test_split(dataset.data,dataset.target,test_size=0.2,random_state=42)
train_x, valid_x, train_y, valid_y = train_test_split(train_x,train_y,test_size=0.2,random_state=42)

scaler = StandardScaler()
train_x = scaler.fit_transform(train_x)
valid_x = scaler.transform(valid_x)
test_x = scaler.transform(test_x)

# 超参数搜索 : 网格搜索  随机搜索 遗传算法 启发式搜索
# 用skelarn进行随机搜索 : 定义模型构造函数并转换成sklearn模型 -> 定义参数分布 -> 随机搜索 -> 筛选模型

# 1. 定义模型构造函数并转换成sklearn模型
# 构造函数的参数就是要搜索的超参数
def build_model(hidden_layers, layer_size, lr):
    model = keras.Sequential()
    model.add(keras.layers.Dense(layer_size, activation='relu',input_shape=train_x.shape[1:]))
    for _ in range(hidden_layers-1):
        model.add(keras.layers.Dense(layer_size,activation='relu'))
    model.add(keras.layers.Dense(1))

    model.compile(loss='mse',optimizer = keras.optimizers.SGD(lr))

    return model 

model_sklearn = keras.wrappers.scikit_learn.KerasRegressor(build_model)

# 2.定义参数分布
# 超参数搜索的几个分布:https://blog.csdn.net/weixin_30505485/article/details/98294718
import scipy
params_distribution = {
    "hidden_layers" : scipy.stats.randint(1,4), # 整数均匀分布 可以取到1,2,3,4
    "layer_size":scipy.stats.randint(1,100),
    # "lr" : scipy.stats.reciprocal(1e-4,1e-2)  # 不是按数值 按比例的均匀分布 [此处用分布会报错 暂时不知道原因]
    "lr" : [0.0001,0.0003,0.001,0.003,0.01,0.03]
}

# 3.随机搜索
# cv是一个参数 cross_validation
from sklearn.model_selection import RandomizedSearchCV


model_sklearn_randomserch = RandomizedSearchCV(model_sklearn,params_distribution,n_iter=10)
model_sklearn_randomserch.fit(train_x,train_y,epochs=10)

print(model_sklearn_randomserch.best_estimator_)
print(model_sklearn_randomserch.best_params_)
print(model_sklearn_randomserch.best_score_)

model = model_sklearn_randomserch.best_estimator_.model
model.evaluate(test_x,test_y)

